#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <queue>

using namespace std;
vector<vector<int>> game_map;
pair<float, float> scoutA_pos;
pair<float, float> gunnerA_pos;
pair<float, float> engineerA_pos;
pair<float, float> dynamiterA_pos;
pair<float, float> scoutB_pos;
pair<float, float> gunnerB_pos;
pair<float, float> engineerB_pos;
pair<float, float> dynamiterB_pos;
float baseA_hp;
float baseB_hp;
float scoutA_hp;
float gunnerA_hp;
float engineerA_hp;
float dynamiterA_hp;
float scoutB_hp;
float gunnerB_hp;
float engineerB_hp;
float dynamiterB_hp;
struct Bullet {
    float x;
    float y;
    float vx;
    float vy;
};
vector<Bullet> bulletA;
vector<Bullet> bulletB;
struct DefenseWork {
    string type;
    float x;
    float y;
    float hp;
};
vector<DefenseWork> defense_workA;
vector<DefenseWork> defense_workB;
int frame_count;


// -------------- 死亡判断相关 ---------------


// 定义己方士兵类型
enum SoldierType { SCOUT, GUNNER, ENGINEER, DYNAMITER };
// 全体士兵类型
enum SoldierType_ALL { SCOUTA, GUNNERA, ENGINEERA, DYNAMITERA, SCOUTB, GUNNERB, ENGINEERB, DYNAMITERB };

map<SoldierType_ALL, bool> isVisible;

typedef pair<float, float> PFF;
typedef pair<int, int> PII;

vector<vector<int>> map_(34, vector<int>(34, 0));

//// 获取己方角色位置
//PFF getPlayerPos(SoldierType player) {
//    PFF playerPos;
//    switch (player) {
//    case SCOUT:
//        playerPos = scoutB_pos;
//        break;
//    case GUNNER:
//        playerPos = gunnerB_pos;
//        break;
//    case ENGINEER:
//        playerPos = engineerB_pos;
//        break;
//    case DYNAMITER:
//        playerPos = dynamiterB_pos;
//        break;
//    }
//    return playerPos;
//}
//
//PFF getEnemyPos(SoldierType player) {
//    PFF playerPos;
//    switch (player) {
//    case SCOUT:
//        playerPos = scoutA_pos;
//        break;
//    case GUNNER:
//        playerPos = gunnerA_pos;
//        break;
//    case ENGINEER:
//        playerPos = engineerA_pos;
//        break;
//    case DYNAMITER:
//        playerPos = dynamiterA_pos;
//        break;
//    }
//    return playerPos;
//}


PFF getPlayerPos(SoldierType player) {
    PFF playerPos;
    switch (player) {
    case SCOUT:
        playerPos = scoutB_pos;
        break;
    case GUNNER:
        playerPos = gunnerB_pos;
        break;
    case ENGINEER:
        playerPos = engineerB_pos;
        break;
    case DYNAMITER:
        playerPos = dynamiterB_pos;
        break;
    }
    return playerPos;
}

PFF getEnemyPos(SoldierType player) {
    PFF playerPos;
    switch (player) {
    case SCOUT:
        playerPos = scoutA_pos;
        break;
    case GUNNER:
        playerPos = gunnerA_pos;
        break;
    case ENGINEER:
        playerPos = engineerA_pos;
        break;
    case DYNAMITER:
        playerPos = dynamiterA_pos;
        break;
    }
    return playerPos;
}

string getPlayerString(SoldierType player) {
    string playerStr;
    switch (player) {
    case SCOUT:
        playerStr = "Scout";
        break;
    case GUNNER:
        playerStr = "Gunner";
        break;
    case ENGINEER:
        playerStr = "Engineer";
        break;
    case DYNAMITER:
        playerStr = "Dynamiter";
        break;
    }
    return playerStr;
}

void updateMap() {
    if (frame_count % 20 == 0) map_ = game_map;
    // 敌人坐标集合
    vector<PFF> enemyPositions = { scoutA_pos, gunnerA_pos, engineerA_pos, dynamiterA_pos };

    for (const auto& enemyPos : enemyPositions) {
        if (abs(enemyPos.first) > 1e-3 && abs(enemyPos.second) > 1e-3) {
            int posX = ceil(enemyPos.first) - 1;
            int posY = ceil(enemyPos.second) - 1;
            map_[posX][posY] = 4; // 
        }
    }
}

PII findAccessibleNeighbor(PII point) {
    const int dx[] = { -1, 0, 1, 0 }; // 
    const int dy[] = { 0, 1, 0, -1 };

    for (int i = 0; i < 4; ++i) {
        int nx = point.first + dx[i];
        int ny = point.second + dy[i];

        if (nx >= 0 && nx < 34 && ny >= 0 && ny < 34 && map_[nx][ny] == 1) {
            return { nx, ny };
        }
    }
    // 返回不可到达
    return { -1, -1 };
}

// BFS寻路算法 返回最短路径
int bfs(PII start, PII& end, vector<vector<PII>>& prev) {
    updateMap();
    // 地图长度
    int rows = 34;
    int cols = 34;

    // 初始化标记数组
    vector<vector<bool>> visited(rows, vector<bool>(cols, false));
    prev.assign(rows, vector<PII>(cols, { -1, -1 }));

    //坐标映射问题
    start.first = start.first - 1;
    start.second = start.second - 1;
    end.first = end.first - 1;
    end.second = end.second - 1;


    //如果目标处站了一个敌人
    if (map_[end.first][end.second] == 4) {
        PII newEnd = findAccessibleNeighbor(end); // 
        if (newEnd.first != -1 && newEnd.second != -1) {
            // 更新新的节点
            end = newEnd;
            //返回0~33
        }
        else {
            return -1;
        }
    }
    


    queue<pair<PII, int>> q;
    q.push({ start, 0 });

    const int dx[] = { -1, 0, 1, 0, 1, 1, -1, -1 };
    const int dy[] = { 0, 1, 0, -1, 1, -1, 1, -1 };

    while (!q.empty()) {
        PII current = q.front().first;
        int dist = q.front().second;
        q.pop();

        if (current == end) {
            return dist;
        }

        for (int i = 0; i < 8; ++i) {
            int nx = current.first + dx[i];
            int ny = current.second + dy[i];

            // 检查边界条件和有效条件
            if (nx >= 0 && nx < rows && ny >= 0 && ny < cols && map_[nx][ny] == 1 && !visited[nx][ny]) {
                if (i < 4 || (map_[current.first][ny] != 1 && map_[nx][current.second] != 1)) {
                    visited[nx][ny] = true;
                    prev[nx][ny] = current;
                    q.push({ {nx, ny}, dist + 1 });
                }
            }
        }
    }

    // 如果没有找到路径
    return -1;
}


// 移动角色
void moveCharacter(SoldierType soldier, float targetX, float targetY) {
    cout << "move ";

    // 根据士兵类型输出相应指令
    switch (soldier) {
    case SCOUT:
        cout << "Scout ";
        break;
    case GUNNER:
        cout << "Gunner ";
        break;
    case ENGINEER:
        cout << "Engineer ";
        break;
    case DYNAMITER:
        cout << "Dynamiter ";
        break;
    }

    // 输出目标位置
    cout << targetX << " " << targetY << endl;
}

void moveCharacterWithShortestPath(SoldierType player, PII& target) {
    PFF playerPos = getPlayerPos(player);
    PII start = { ceil(playerPos.first), ceil(playerPos.second) };
    vector<vector<PII>> prev;
    PII tempTarget = target;
    int shortestPath = bfs(start, tempTarget, prev);

    if (shortestPath != -1 && shortestPath != 0) {
        start = { start.first - 1, start.second - 1 };
        //保证target为映射前的数据
        PII current;
        if (tempTarget == target) current = { target.first - 1, target.second - 1 };
        else {
            //如果修改了，tempTarget: 0~33
            current = tempTarget;
            target = { tempTarget.first + 1, tempTarget.second + 1 };
            //返回1~34
        }

        while (current != start) {
            if (prev[current.first][current.second] == start) break;
            current = prev[current.first][current.second];
        }
        moveCharacter(player, current.first + 1 - 0.5, current.second + 1 - 0.5);
    }
}

int scoutB_state, gunnerB_state, engineerB_state, dynamiterB_state;

void moveOnTheWay(SoldierType player, vector<PII>& waypoints) {
    PFF playerPos;
    int state = 0;
    switch (player) {
    case SCOUT:
        playerPos = scoutB_pos;
        state = scoutB_state;
        break;
    case GUNNER:
        playerPos = gunnerB_pos;
        state = gunnerB_state;
        break;
    case ENGINEER:
        playerPos = engineerB_pos;
        state = engineerB_state;
        break;
    case DYNAMITER:
        playerPos = dynamiterB_pos;
        state = dynamiterB_state;
        break;
    }
    if (state >= waypoints.size()) return;

    PII current = waypoints[state];
    PII tempCurrent = current;
    moveCharacterWithShortestPath(player, current);
    if (current != tempCurrent) waypoints[state] = current;
    //到达目标，进入下一个状态，开始下一种移动
    if (ceil(playerPos.first) == current.first && ceil(playerPos.second) == current.second) {
        switch (player) {
        case SCOUT:
            scoutB_state++;
            break;
        case GUNNER:
            gunnerB_state++;
            break;
        case ENGINEER:
            engineerB_state++;
            break;
        case DYNAMITER:
            dynamiterB_state++;
            break;
        }
    }
}


// 更新不可见性
void updateIsVisible() {
    //初始化为不可见
    for (auto& pair : isVisible) {
        pair.second = false;
    }
}

bool isCharacterVisible(SoldierType_ALL player) {
    return isVisible[player];
}


// ----------- 配置（不要删） --------------
static int gunner_stop = 0; // 让Gunner停一下
static bool is_scout_skill = false; // scout开技能了没有
static bool s_skill = false; // scout放照明弹

//static Node engineer_skill[] = { {24, 1}, {27.5, 6.5}, {30.5, 10} }; // 放地雷的三点（直接写到路径数组里面了）
static int engineer_skill_idx = 0; // 放陷阱的次数
static int e_skill = 0; // 放buff的次数

static int d_skill = 0; // d放技能的次数
static bool killed = false;


// 判断敌人来基地了吗
bool enemy_in(pair<float, float> enemy) {

    if (enemy.first >= 23 && enemy.second <= 9) {
        return true;
    }
    return false;
}

float getDistance(pair<float, float> me, pair<float, float> enemy) {
    float dx = me.first - enemy.first;
    float dy = me.second - enemy.second;
    return sqrt(dx * dx + dy * dy);
}

/* 判断离me最近的人 */
SoldierType getMostClose(pair<float, float> me) {
    float a = getDistance(me, gunnerA_pos);
    float b = getDistance(me, engineerA_pos);
    float c = getDistance(me, scoutA_pos);
    float d = getDistance(me, dynamiterA_pos);

    float arr[] = { a, b, c, d };

    float mind = arr[0];
    for (int i = 1; i < 4; i++) {
        if (arr[i] < mind) {
            mind = arr[i];
        }
    }


    if (mind == arr[0]) {
        return GUNNER;
    }
    else if (mind == arr[1]) {
        return ENGINEER;
    }
    else if (mind == arr[2]) {
        return SCOUT;
    }
    else {
        return DYNAMITER;
    }
}

/* 判断是否到达的函数 */
bool isRightHere(pair<float, float> player, PII target) {
    if (ceil(player.first) == target.first && ceil(player.second) == target.second) return true;
    return false;
}



void init_input() {
    string init_str;
    cin >> init_str;

    int n, m;
    cin >> n >> m;
    for (int i = 0; i < n; i++) {
        vector<int> tmp(m, 0);
        for (int j = 0; j < m; j++) {
            cin >> tmp[j];
        }
        game_map.push_back(tmp);
    }
    cin >> init_str;

}

void baseMonitor();

// 士兵数据输入
void solider_input() {
    string pos;
    cin >> pos;
    int count;
    cin >> count;
    cerr << "solider count " << count << endl;
    for (int i = 0; i < count; i++) {
        string type;
        string team;
        float x;
        float y;
        float hp;
        cin >> pos >> team >> pos >> type >> pos >> x >> pos >> y >> pos >> hp;
        if (team == "A" || team == "ACloaking") {
            if (type == "Scout") {
                scoutA_pos.first = x;
                scoutA_pos.second = y;
                scoutA_hp = hp;
                isVisible[SCOUTA] = true;
            }
            if (type == "Gunner") {
                gunnerA_pos.first = x;
                gunnerA_pos.second = y;
                gunnerA_hp = hp;
                isVisible[GUNNERA] = true;
            }
            if (type == "Engineer") {
                engineerA_pos.first = x;
                engineerA_pos.second = y;
                engineerA_hp = hp;
                isVisible[ENGINEERA] = true;
            }
            if (type == "Dynamiter") {
                dynamiterA_pos.first = x;
                dynamiterA_pos.second = y;
                dynamiterA_hp = hp;
                isVisible[DYNAMITERA] = true;
            }
        }
        else if (team == "B" || team == "BCloaking") {
            if (type == "Scout") {
                scoutB_pos.first = x;
                scoutB_pos.second = y;
                scoutB_hp = hp;
                isVisible[SCOUTB] = true;
            }
            if (type == "Gunner") {
                gunnerB_pos.first = x;
                gunnerB_pos.second = y;
                isVisible[GUNNERB] = true;
                gunnerB_hp = hp;
            }
            if (type == "Engineer") {
                engineerB_pos.first = x;
                engineerB_pos.second = y;
                engineerB_hp = hp;
                isVisible[ENGINEERB] = true;
            }
            if (type == "Dynamiter") {
                dynamiterB_pos.first = x;
                dynamiterB_pos.second = y;
                dynamiterB_hp = hp;
                isVisible[DYNAMITERB] = true;
            }
        }
    }

    baseMonitor(); // 嗨嗨

    cin >> pos;
}

// 子弹数据输入
void bullet_input() {
    bulletA.clear();
    bulletB.clear();
    string tmp;
    cin >> tmp;

    int bullet_count;
    cin >> bullet_count;

    cerr << "bullet count " << bullet_count << endl;

    for (int i = 0; i < bullet_count; i++) {
        Bullet bullet;
        string team;
        string tmp;
        // scanf("Team %s type Bullet x %f z %f vx %f vz %f\n", team.data(), &bullet.x, &bullet.y, &bullet.vx, &bullet.vy);
        cin >> tmp >> team >> tmp >> tmp >> tmp >> bullet.x >> tmp >> bullet.y >> tmp >> bullet.vx >> tmp >> bullet.vy;
        if (team == "A") {
            bulletA.push_back(bullet);
        }
        else {
            bulletB.push_back(bullet);
        }
    }

    cin >> tmp;
}

// 防御工事数据输入
void defense_work_input() {
    string tmp;
    cin >> tmp;
    int count;
    cin >> count;
    cerr << "Defense count " << count << endl;
    for (int i = 0; i < count; i++) {
        string team;
        DefenseWork defense_work;
        string tmp;
        // scanf("Team %s type %s x %f z %f\n", team.data(), defense_work.type.data(), &defense_work.x, &defense_work.y);
        cin >> tmp >> team >> tmp >> defense_work.type >> tmp >> defense_work.x >> tmp >> defense_work.y >> tmp >> defense_work.hp;
        if (team == "A") {
            defense_workA.push_back(defense_work);
        }
        else if (team == "B") {
            defense_workB.push_back(defense_work);
        }
    }

    cin >> tmp;
}

// 基地血量输入
void base_input() {
    string tmp;
    cin >> tmp;
    cin >> tmp >> baseA_hp;
    cin >> tmp >> baseB_hp;
    cin >> tmp;
}

void per_frame_input() {
    string  frame;

    cin >> frame >> frame_count;
    cerr << frame << ":" << frame_count << endl;

    updateIsVisible(); // 更新不可见性

    solider_input();
    bullet_input();
    defense_work_input();
    base_input();

    cin >> frame >> frame_count;
}

void skill(SoldierType player, int skillnum) {
    string playerStr = getPlayerString(player);
    cout << "skill " << playerStr << " " << skillnum << endl;
    /*if (player == ENGINEER && skillnum == 2) {
        engineer_skill_idx++;
    }*/
}

void skill(SoldierType player, int skillnum, int x, int y) {
    string playerStr = getPlayerString(player);
    cout << "skill " << playerStr << " " << skillnum << " " << x << " " << y << endl;
    /*if (player == DYNAMITER && skillnum == 1) d_skill++;
    if (player == SCOUT && skillnum == 2) s_skill = true;*/
}

void skill(SoldierType player, int skillnum, SoldierType enemy) {
    string playerStr = getPlayerString(player);
    PFF enemyPos = getEnemyPos(enemy);
    //skill(player, skillnum, enemyPos.first, enemyPos.second);
    skill(player, skillnum, ceil(enemyPos.first), ceil(enemyPos.second));
}

void shut(SoldierType player, float x, float y) {
    string playerStr = getPlayerString(player);
    cout << "shut " << playerStr << " " << x << " " << y << endl;
}

void shut(SoldierType player, SoldierType enemy) {
    PFF enemyPos = getEnemyPos(enemy);
    shut(player, enemyPos.first, enemyPos.second);
}

bool isRightHere(SoldierType player, PII target) {
    PFF playerPos = getPlayerPos(player);
    if (ceil(playerPos.first) == target.first && ceil(playerPos.second) == target.second) return true;
    return false;
}

/* 判断离me最近的人 */
SoldierType getTheMostCloseEnemy(SoldierType player) {
    PFF playerPos = getPlayerPos(player);
    float a = getDistance(playerPos, gunnerA_pos);
    float b = getDistance(playerPos, engineerA_pos);
    float c = getDistance(playerPos, scoutA_pos);
    float d = getDistance(playerPos, dynamiterA_pos);

    float arr[] = { a, b, c, d };

    float mind = arr[0];
    for (int i = 1; i < 4; i++) {
        if (arr[i] < mind) {
            mind = arr[i];
        }
    }


    if (mind == arr[0]) {
        return GUNNER;
    }
    else if (mind == arr[1]) {
        return ENGINEER;
    }
    else if (mind == arr[2]) {
        return SCOUT;
    }
    else {
        return DYNAMITER;
    }
}

bool isEnemyInBase(SoldierType enemy) {
    PFF enemyPos = getEnemyPos(enemy);
    if (enemyPos.first <= 11 && enemyPos.second >= 23) return true;
    return false;
}

//int func() {
//    int cnt = 0;
//    if (isEnemyInBase(SCOUT)) cnt++;
//
//    return cnt;
//}

// ----------- 路径数组 -------------
// 到底设不设中间节点，可以多试一下
// 


// 设置中间节点，中间节点是18，8
//PII middle = { 10, 10 }; // 15, 27 // 
//// 中路进攻：24, 17
//// 小路进攻：8, 3
//
//PII trap1 = { 10, 33 };
//PII trap2 = { 7, 28 };
//PII trap3 = { 4, 25 };
//PII flash = { 22, 4 }; // 
//
//static vector<PII> sway = { middle, {28, 2} };
//static vector<PII> gway = { middle, {29, 3} };
//static vector<PII> eway = { middle, {30, 3} };
//static vector<PII> dway = { middle, {26, 2} };
//
//static int d_stop = 0;
//static int g_stop = 0;
//static int e_stop = 0;
//static int s_stop = 0;



inline void moveG(float x, float y) {
    cout << "move Gunner " << x << " " << y << endl;
}
inline void moveE(float x, float y) {
    cout << "move Engineer " << x << " " << y << endl;
}
inline void moveS(float x, float y) {
    cout << "move Scout " << x << " " << y << endl;
}
inline void moveD(float x, float y) {
    cout << "move Dynamiter " << x << " " << y << endl;
}

inline void shutG(float x, float y) {
    cout << "shut Gunner " << x << " " << y << endl;
}
inline void shutE(float x, float y) {
    cout << "shut Engineer " << x << " " << y << endl;
}
inline void shutS(float x, float y) {
    cout << "shut Scout " << x << " " << y << endl;
}
inline void shutD(float x, float y) {
    cout << "shut Dynamiter " << x << " " << y << endl;
}



bool eAdie() {
    return !isCharacterVisible(ENGINEERA);
}

bool dAdie() {
    return !isCharacterVisible(DYNAMITERA);
}

bool gAdie() {
    return !isCharacterVisible(GUNNERA);
}

bool sAdie() {
    return !isCharacterVisible(SCOUTA);
}

/* 开火速度翻倍
持续时间为 5s，CD 10s*/
inline void skillG() {
    cout << "skill Gunner 1" << endl;
}
/*放置一个阵地在脚下，可重叠，全局一共3个，不可回复
阵地血量50，可提供50%子弹闪避*/
inline void skillE1() {
    cout << "skill Engineer 1" << endl;
}
/*放置一个铁丝网在脚下，可重叠，全局一共3个，不可回复
铁丝网血量50，让敌方的速度降低到35%*/
inline void skillE2() {
    cout << "skill Engineer 2" << endl;
}
/*隐身，阵营变成ACloaking或BCloaking
持续5s CD10s*/
inline void skillS1() {
    cout << "skill Scout 1" << endl;
}
/*发射一个照明弹解除敌方Scout的隐身，破隐范围是一个长宽为6的长方体
持续1.5s CD 5s*/
inline void skillS2(int x, int y) {
    cout << "skill Scout 2 " << x << " " << y << endl;
}
/*全局一共3颗地雷，不可回复，请思考如何合理使用
投掷一个地雷，地雷伤害50，半径2.5，伤害递减 hurt = 50 - 10*distance，无友方伤害
最后两个是整数，表示地图的坐标，如果坐标上的格子不是墙或者基地，就在格子中间生成地雷，否则就忽略
同时坐标和士兵的距离要小于10，不然就忽略*/
inline void skillD(int x, int y) {
    cout << "skill Dynamiter 1 " << x << " " << y << endl;
}


/* 判断是否到达的函数 */
bool isHere(pair<float, float> player, PII target) {
    if (ceil(player.first) == target.first && ceil(player.second) == target.second) return true;
    return false;
}

bool nearEnemyBase(pair<float, float> player) {
    float x = player.first;
    float y = player.second;
    if (x >= 19) {
        return true;
    }
    return false;
}


// ----------- 路径数组 -------------

static vector<PII> sway = { {4, 27} }; // 31, 8
static vector<PII> gway = { {2, 28} };
// static vector<PII> eway = { {7, 27}, {8, 27}, {27, 8}, {27, 7}, {27, 6} };
static vector<PII> dway = { {7, 33} }; // 28 2

PII middle = { 9, 4 }; // 28, 31
PII d_middle = { 7, 16 };
static vector<PII> saway = { middle, {31, 5} };
static vector<PII> daway = { d_middle, middle, {30, 5} };
static vector<PII> gaway = { middle, {28, 4} };
static vector<PII> eaway = { middle, {29, 2} };


// 开局占位的延时
static int d_stop = 0;
static int g_stop = 0;
const int GSTOP = 10;
const int DSTOP = 120;
// 攻击的延时
static int e_stop_a = 0;
static int g_stop_a = 0;
static int d_stop_a = 0;
const int ESTOPA = 110; // 70
const int GSTOPA = 100; // 50
const int DSTOPA = 40;


static map<char, int> beat = { {'g', 0}, {'d', 0}, {'e', 0}, {'s', 0} };

bool rush() {
    // cout << "HP " << baseB_hp << endl;
    return baseA_hp <= 4125; // 4125
}

// ============== 精准寻路 ==================
struct Node {
    float x;
    float y;
    Node() {
        this->x = 0;
        this->y = 0;
    }
    Node(float x, float y) :x(x), y(y) {
    }
};
// ex：基本0.3，大概0.5，严格0.1
bool eq(float x, float y, float ex = 0.1) {
    if (abs(x - y) < ex) {
        return true;
    }
    return false;
}
static Node pE[] = { {6.5, 26.5}, {7.5, 26.5}, {7.5, 27.5}, {7.5, 28.5} }; // 路径数组
static int idxE = 0; // idx，记得置零
void onTheWayE(Node* pE, int len) {
    //cout << "myid" << idxE << " " << pE[idxE].x << " " << pE[idxE].y << endl;
    float x = pE[idxE].x;
    float y = pE[idxE].y;
    moveE(x, y);

    if (eq(engineerB_pos.first, x) && eq(engineerB_pos.second, y)) { // 如果到了当前目标
        idxE++;

        int length = len / sizeof(pE[0]);
        if (eq(engineerB_pos.first, pE[length - 1].x) && eq(engineerB_pos.second, pE[length - 1].y)) { // 如果当前目标是终点
            idxE = 0;
            return;
        }
    }
}

static bool go = true;

enum BaseState { PEACEFUL, UNDERATTACK, ATTACKED }; // 0：还未被攻击，1：正在被攻击，2，我们已全歼敌人
static BaseState base_state = PEACEFUL;
static int base_hp = -1; // static
void baseMonitor() {
    if (base_hp != -1) {
        int det = base_hp - baseB_hp;

        //cout << "det " << det << endl;
        //cout << "base_state " << base_state << endl;

        if ((det == 2 || det == 3 || det == 4 || det == 5) && base_state == PEACEFUL) {
            base_state = UNDERATTACK;
            go = false;
        }
        else if (det == 1 && base_state == UNDERATTACK && dAdie() && gAdie() && eAdie() && sAdie()) {
            base_state = ATTACKED;
        }
    }
    base_hp = baseB_hp;
}

// 获取己方角色位置
PFF getPlayerPos(SoldierType player);
// 获取敌方角色位置
PFF getEnemyPos(SoldierType player);
// 判断是否能射击（障碍物判断）
// 浮点坐标转换成整数坐标
PII positionConvert(PFF p) { return { (int)(p.first), (int)(p.second) }; }

bool canShoot(int playerX, int playerY, int enemyX, int enemyY);

// 判断player是否能射击enemy
bool canShoot(SoldierType player, SoldierType enemy) {
    PFF enemyPos = getEnemyPos(enemy), playerPos = getPlayerPos(player);
    PII enemyPos_ = positionConvert(enemyPos);
    PII playerPos_ = positionConvert(playerPos);
    return canShoot(playerPos_.first, playerPos_.second, enemyPos_.first, enemyPos_.second);
}

float getDistance(float x1, float y1, float x2, float y2) { return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); }
bool canThrowGrenades(float x, float y) {
    /*cout << "TRUE" << x << " " << y << endl;
    if (x == 0 && y == 0) return false;*/
    SoldierType player = DYNAMITER;
    PFF playerPos = getPlayerPos(player);
    float distance = getDistance(playerPos.first, playerPos.second, x, y);
    if (distance < 10.0) {
        //cout << "TRUE " << playerPos.first << " " << playerPos.second << " " << endl;
        return true;
    }
    return false;
}

static bool isleave = false;


void output_command() {
    // write your code

    // ============== G =============
    SoldierType me = GUNNER;
    if (g_stop == GSTOP) { // 先停一下

        if (base_state == ATTACKED || (rush() && !isleave)) { // 进攻
            if (g_stop_a == GSTOPA) { // 停一下再冲
                if (isHere(gunnerB_pos, gaway[gaway.size() - 1])) { // Gunner到达目标

                    // --------------- gunner攻击 ------------------
                    if (!dAdie() && canShoot(me, DYNAMITER)) {
                        // 攻击dynamiterB
                        skillG();
                        shutG(dynamiterA_pos.first, dynamiterA_pos.second);
                    }
                    else if (!gAdie() && canShoot(me, GUNNER)) {
                        // 攻击gunnerB
                        skillG();
                        shutG(gunnerA_pos.first, gunnerA_pos.second);
                    }
                    else if (!sAdie() && canShoot(me, SCOUT)) {
                        // 攻击scoutB
                        skillG();
                        shutG(scoutA_pos.first, scoutA_pos.second);
                    }
                    else if (!eAdie() && canShoot(me, ENGINEER)) {
                        // 攻击engineerB
                        skillG();
                        shutG(engineerA_pos.first, engineerA_pos.second);
                    }
                    
                    /*else {
                        shutG(14, 6.5);
                    }*/
                }
                else if (!isHere(gunnerB_pos, gaway[gaway.size() - 1])) { // gunner在路上
                    moveOnTheWay(GUNNER, gaway);
                }
            }
            else {
                g_stop_a++;
            }
        }
        else if (isHere(gunnerB_pos, gway[gway.size() - 1])) { // Gunner到达目标
            // --------------- gunner攻击 ------------------
            if (!dAdie() && canShoot(me, DYNAMITER)) {
                // 攻击dynamiterB
                skillG();
                shutG(dynamiterA_pos.first, dynamiterA_pos.second);
            }
            else if (!gAdie() && canShoot(me, GUNNER)) {
                // 攻击gunnerB
                skillG();
                shutG(gunnerA_pos.first, gunnerA_pos.second);
            }
            else if (!sAdie() && canShoot(me, SCOUT)) {
                // 攻击scoutB
                skillG();
                shutG(scoutA_pos.first, scoutA_pos.second);
            }
            else if (!eAdie() && canShoot(me, ENGINEER)) {
                // 攻击engineerB
                skillG();
                shutG(engineerA_pos.first, engineerA_pos.second);
            }
            else {
                shutG(14.5, 27.5);
            }
        }
        else if (!isHere(gunnerB_pos, gway[gway.size() - 1])) { // gunner在路上
            moveOnTheWay(GUNNER, gway);
        }

    }
    else {
        g_stop++;
    }


    // ============= D ===============
    // ------------- 移动D ---------------
    me = DYNAMITER;
    if (d_stop == DSTOP) {

        if (base_state == ATTACKED || (rush() && base_state == PEACEFUL)) { // 进攻
            if (d_stop_a == DSTOPA) {
                if (d_skill != 3) { // 看见人就扔炸弹（这个要放最前面）
                    if (!eAdie() && canThrowGrenades(engineerA_pos.first, engineerA_pos.second && beat['e'] != 2)) {
                        skillD(engineerA_pos.first, engineerA_pos.second);
                        d_skill++;
                        beat['e']++;
                    }
                    if (!dAdie() && canThrowGrenades(dynamiterA_pos.first, dynamiterA_pos.second) && beat['d'] != 2) {
                        skillD(dynamiterA_pos.first, dynamiterA_pos.second);
                        d_skill++;
                        beat['d']++;
                    }
                    else if (!gAdie() && canThrowGrenades(gunnerA_pos.first, gunnerA_pos.second) && beat['g'] != 2) {
                        skillD(gunnerA_pos.first, gunnerA_pos.second);
                        d_skill++;
                        beat['g']++;
                    }
                    else if (!sAdie() && canThrowGrenades(scoutA_pos.first, scoutA_pos.second) && beat['s'] != 2) {
                        skillD(scoutA_pos.first, scoutA_pos.second);
                        d_skill++;
                        beat['s']++;
                    }
                }
                if (isHere(dynamiterB_pos, daway[daway.size() - 1])) { // D到达目标后开始攻击

                    // --------------- dynamiter攻击 ------------------

                    if (!dAdie() && canShoot(me, DYNAMITER)) {
                        // 攻击dynamiterA
                        shutD(dynamiterA_pos.first, dynamiterA_pos.second);
                    }
                    else if (!gAdie() && canShoot(me, GUNNER)) {
                        // 攻击gunnerA
                        shutD(gunnerA_pos.first, gunnerA_pos.second);
                    }
                    else if (!eAdie() && canShoot(me, ENGINEER)) {
                        // 攻击engineerA
                        shutD(engineerA_pos.first, engineerA_pos.second);
                    }
                    else if (!sAdie() && canShoot(me, SCOUT)) {
                        // 攻击scoutA
                        shutD(scoutA_pos.first, scoutA_pos.second);
                    }
                    
                    /*else {
                        shutD(7.5, 16.5);
                    }*/
                }
                else if (!isHere(dynamiterB_pos, daway[daway.size() - 1])) { // D在路上
                    moveOnTheWay(DYNAMITER, daway);
                }
            }
            else {
                d_stop_a++;
            }
            
        }
        else if (d_skill != 3 && isHere(dynamiterB_pos, dway[0])) { // 扔炸弹

            // char c = getMostClose(dynamiterA_pos); // 不能攻击最近的一个，应该先干掉炸弹人，还要加上半径为10的判断

            // --------------- dynamiter攻击 ------------------

            if (!dAdie() && canThrowGrenades(dynamiterA_pos.first, dynamiterA_pos.second) && beat['d'] != 2) { // enemy_in(dynamiterB_pos)
                // 攻击dynamiterA
                skillD(dynamiterA_pos.first, dynamiterA_pos.second);
                d_skill++;
                beat['d']++;
            }
            else if (!gAdie() && canThrowGrenades(gunnerA_pos.first, gunnerA_pos.second) && beat['g'] != 2) { // enemy_in(gunnerB_pos) &&
                // 攻击gunnerA
                skillD(gunnerA_pos.first, gunnerA_pos.second);
                d_skill++;
                beat['g']++;
            }
            else if (!eAdie() && canThrowGrenades(engineerA_pos.first, engineerA_pos.second) && beat['e'] != 2) { // enemy_in(engineerB_pos) &&
                // 攻击engineerA
                skillD(engineerA_pos.first, engineerA_pos.second);
                d_skill++;
                beat['e']++;
            }
            else if (!sAdie() && canThrowGrenades(scoutA_pos.first, scoutA_pos.second) && beat['s'] != 2) { // enemy_in(scoutB_pos) &&
                // 攻击scoutA
                skillD(scoutA_pos.first, scoutA_pos.second);
                d_skill++;
                beat['s']++;
            }
            else {
                shutD(6.5, 15.5);
            }
        }
        else if (isHere(dynamiterB_pos, dway[dway.size() - 1])) { // D到达目标

            // --------------- dynamiter攻击 ------------------

            if (!dAdie() && canShoot(me, DYNAMITER)) {
                // 攻击dynamiterA
                shutD(dynamiterA_pos.first, dynamiterA_pos.second);
            }
            else if (!gAdie() && canShoot(me, GUNNER)) {
                // 攻击gunnerA
                shutD(gunnerA_pos.first, gunnerA_pos.second);
            }
            else if (!sAdie() && canShoot(me, SCOUT)) {
                // 攻击scoutA
                shutD(scoutA_pos.first, scoutA_pos.second);
            }
            else if (!eAdie() && canShoot(me, ENGINEER)) {
                // 攻击engineerA
                shutD(engineerA_pos.first, engineerA_pos.second);
            }
            else {
                shutD(6.5, 15.5);
            }
        }
        else if (!isHere(dynamiterB_pos, dway[dway.size() - 1])) { // D在路上
            moveOnTheWay(DYNAMITER, dway);
        }

    }
    else {
        d_stop++;
    }





    // ============= E ===============
    me = ENGINEER;
    int length = sizeof(pE) / sizeof(pE[0]);
    if (eq(engineerB_pos.first, pE[0].x) && eq(engineerB_pos.second, pE[0].y) && engineer_skill_idx == 0) { // 第一个铁丝网
        skillE2();
        engineer_skill_idx++;
    }
    else if (eq(engineerB_pos.first, pE[1].x) && eq(engineerB_pos.second, pE[1].y) && engineer_skill_idx == 1) { // 第一个铁丝网
        skillE2();
        engineer_skill_idx++;
    }
    else if (eq(engineerB_pos.first, pE[2].x) && eq(engineerB_pos.second, pE[2].y) && engineer_skill_idx == 2) { // 第一个铁丝网
        skillE2();
        engineer_skill_idx++;
    }
    else if (base_state == ATTACKED || (rush() && base_state == PEACEFUL)) { // 出击
        if (e_stop_a == ESTOPA) { // 先停一下
            if (isHere(engineerB_pos, eaway[eaway.size() - 1])) { // Gunner到达目标

                    // --------------- gunner攻击 ------------------
                if (!dAdie() && canShoot(me, DYNAMITER)) {
                    // 攻击dynamiterB
                    skillE1();
                    shutE(dynamiterA_pos.first, dynamiterA_pos.second);
                }
                else if (!gAdie() && canShoot(me, GUNNER)) {
                    // 攻击gunnerB
                    skillE1();
                    shutE(gunnerA_pos.first, gunnerA_pos.second);
                }
                else if (!sAdie() && canShoot(me, SCOUT)) {
                    // 攻击scoutB
                    skillE1();
                    shutE(scoutA_pos.first, scoutA_pos.second);
                }
                else if (!eAdie() && canShoot(me, ENGINEER)) {
                    // 攻击engineerB
                    skillE1();
                    shutE(engineerA_pos.first, engineerA_pos.second);
                }
            }
            else if (!isHere(engineerB_pos, eaway[eaway.size() - 1])) { // gunner在路上
                moveOnTheWay(ENGINEER, eaway);
            }
        }
        else {
            e_stop_a++;
        }
    }
    else if (!eq(engineerB_pos.first, pE[length - 1].x) || !eq(engineerB_pos.second, pE[length - 1].y)) { // 在路上
        onTheWayE(pE, sizeof(pE));
    }
    else {
        // --------------- engineer攻击 ------------------

        if (!dAdie() && canShoot(me, DYNAMITER)) {
            // 攻击dynamiterB
            skillE1();
            shutE(dynamiterA_pos.first, dynamiterA_pos.second);
        }
        else if (!gAdie() && canShoot(me, GUNNER)) {
            // 攻击gunnerB
            skillE1();
            shutE(gunnerA_pos.first, gunnerA_pos.second);
        }
        else if (!sAdie() && canShoot(me, SCOUT)) {
            // 攻击scoutB
            skillE1();
            shutE(scoutA_pos.first, scoutA_pos.second);
        }
        else if (!eAdie() && canShoot(me, ENGINEER)) {
            // 攻击engineerB
            skillE1();
            shutE(engineerA_pos.first, engineerA_pos.second);
        }
        else {
            shutE(7.5, 15.5);
        }
    }


    // =============== S ==================
    me = SCOUT;
    if (base_state == ATTACKED || (rush() && base_state == PEACEFUL)) { // 出击
        // 按道理说应该是冲第一个的scout最先发现敌人（同时要在基地内），然后他立即隐身
        if (((!dAdie() || !gAdie() || !eAdie() || !sAdie()) && nearEnemyBase(scoutB_pos))) {
            skillS1();
        }
        if (isHere(scoutB_pos, saway[saway.size() - 1])) { // Scout到达目标地点
            // 开始射击
            if (!dAdie() && canShoot(me, DYNAMITER)) {
                skillS1();
                shutS(dynamiterA_pos.first, dynamiterA_pos.second);
            }
            else if (!gAdie() && canShoot(me, GUNNER)) {
                skillS1();
                shutS(gunnerA_pos.first, gunnerA_pos.second);
            }
            else if (!sAdie() && canShoot(me, SCOUT)) {
                skillS1();
                shutS(scoutA_pos.first, scoutA_pos.second);
            }
            else if (!eAdie() && canShoot(me, ENGINEER)) {
                skillS1();
                shutS(engineerA_pos.first, engineerA_pos.second);
            }
        }
        else if (!isHere(scoutB_pos, saway[saway.size() - 1])) {
            moveOnTheWay(SCOUT, saway);
        }
    }
    else if (isHere(scoutB_pos, sway[sway.size() - 1])) { // Scout到达目标地点
        // --------------- Scout攻击 ------------------


        // 加隐身！

        if (!dAdie() && canShoot(me, DYNAMITER)) {
            // 攻击dynamiterA
            shutS(dynamiterA_pos.first, dynamiterA_pos.second);
        }
        else if (!gAdie() && canShoot(me, GUNNER)) {
            // 攻击gunnerA
            shutS(gunnerA_pos.first, gunnerA_pos.second);
        }
        else if (!sAdie() && canShoot(me, SCOUT)) {
            // 攻击scoutA
            shutS(scoutA_pos.first, scoutA_pos.second);
        }
        else if (!eAdie() && canShoot(me, ENGINEER)) {
            // 攻击engineerA
            shutS(engineerA_pos.first, engineerA_pos.second);
        }
        else {
            shutS(14.8, 26.5);
        }

    }
    else if (!isHere(scoutB_pos, sway[sway.size() - 1])) {
        // Scout还在路上
        moveOnTheWay(SCOUT, sway);
    }

    cout << "End" << endl;
}

int main() {
    // Debug
    cerr << "Start PlayerB" << endl;
    init_input();

    while (true) {
        per_frame_input();
        output_command();
    }
    return 0;
}

//PFF getPlayerPos(SoldierType player) {
//    PFF playerPos;
//    switch (player) {
//    case SCOUT:
//        playerPos = scoutA_pos;
//        break;
//    case GUNNER:
//        playerPos = gunnerA_pos;
//        break;
//    case ENGINEER:
//        playerPos = engineerA_pos;
//        break;
//    case DYNAMITER:
//        playerPos = dynamiterA_pos;
//        break;
//    }
//    return playerPos;
//}
//
//PFF getEnemyPos(SoldierType player) {
//    PFF playerPos;
//    switch (player) {
//    case SCOUT:
//        playerPos = scoutB_pos;
//        break;
//    case GUNNER:
//        playerPos = gunnerB_pos;
//        break;
//    case ENGINEER:
//        playerPos = engineerB_pos;
//        break;
//    case DYNAMITER:
//        playerPos = dynamiterB_pos;
//        break;
//    }
//    return playerPos;
//}

bool canShoot(int playerX, int playerY, int enemyX, int enemyY) {
    // Bresenham's line algorithm
    int dx = abs(enemyX - playerX);
    int dy = -abs(enemyY - playerY);
    int sx = playerX < enemyX ? 1 : -1;
    int sy = playerY < enemyY ? 1 : -1;
    int err = dx + dy;

    while (true) {
        // 如果到达敌人的位置，表示可以射击
        if (playerX == enemyX && playerY == enemyY) {
            // cout << "keyisheji " << playerX << " " << playerY << " " << enemyX << " " << enemyY << endl;
            return true;
        }

        // 检查当前位置是否有障碍物
        if (map_[playerX][playerY] == 2) return false;

        int e2 = 2 * err;
        if (e2 >= dy) {
            if (playerX == enemyX) break;
            err += dy;
            playerX += sx;
        }
        if (e2 <= dx) {
            if (playerY == enemyY) break;
            err += dx;
            playerY += sy;
        }
    }
    return false; // 路径上有障碍物
}